/*
 * HSM Proxy Project.
 * Copyright (C) 2013 FedICT.
 * Copyright (C) 2013 Frank Cornelis.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.hsm.model.security;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import be.fedict.hsm.entity.AdministratorEntity;

@Stateless
@EJB(name = AdministratorSecurityBean.JNDI_NAME, beanInterface = AdministratorSecurityBean.class)
public class AdministratorSecurityBean {

	private static final Log LOG = LogFactory
			.getLog(AdministratorSecurityBean.class);

	public final static String JNDI_NAME = "java:global/HSMProxyAdministratorSecurityBean";

	@PersistenceContext
	private EntityManager entityManager;

	@EJB
	private SecurityAuditGeneratorBean securityAuditGeneratorBean;

	public static AdministratorSecurityBean getInstance() {
		try {
			InitialContext initialContext = new InitialContext();
			return (AdministratorSecurityBean) initialContext.lookup(JNDI_NAME);
		} catch (NamingException e) {
			throw new RuntimeException("JNDI error: " + e.getMessage(), e);
		}
	}

	public String getAuthenticatedAdministrator(String username,
			String cardNumber) {
		LOG.debug("authenticating " + username);
		if (bootstrap(username, cardNumber)) {
			return username;
		}
		AdministratorEntity administratorEntity = this.entityManager.find(
				AdministratorEntity.class, username);
		if (null == administratorEntity) {
			/*
			 * We register unknown administrators as pending.
			 */
			administratorEntity = new AdministratorEntity(username, cardNumber,
					true);
			this.entityManager.persist(administratorEntity);
			this.securityAuditGeneratorBean.adminAuthenticationError(username);
			return null;
		}
		if (administratorEntity.isPending()) {
			this.securityAuditGeneratorBean.adminAuthenticationError(username);
			return null;
		}
		if (false == cardNumber.equals(administratorEntity.getCardNumber())) {
			/*
			 * Completely useless since the challenged RSA public exponent is
			 * the unique identifier, but anyway.
			 */
			this.securityAuditGeneratorBean.adminAuthenticationError(username);
			return null;
		}
		return username;
	}

	private boolean bootstrap(String username, String cardNumber) {
		if (AdministratorEntity.hasActiveAdministrators(this.entityManager)) {
			return false;
		}
		AdministratorEntity administratorEntity = new AdministratorEntity(
				username, cardNumber, false);
		this.entityManager.persist(administratorEntity);
		return true;
	}
}
